/* eslint-disable no-async-promise-executor */
const model = require("../models/model")

const { decrypt } = require('../models/crypt')

const { Op } = require("sequelize")

const jwt = require('jsonwebtoken')

require('dotenv').config() // 环境变量

const User = model.user.User //获取User模型
const MyGoodsListRate = model.goodsdetailsRate.MyGoodsListRate

const EmailConfig = require('../config/email')
const Redis = require('koa-redis')
//新建连接redis客户端
const Store = Redis({ host: EmailConfig.redis.host, port: EmailConfig.redis.port }).client

// 登陆
exports.login = async(ctx) => {
  const { phone, password, captcha } = ctx.request.body
  // if (process.env.NODE_ENV != 'development' && ctx.session.captcha != captcha.toLowerCase()) {
  //   ctx.fail('验证码有误', -1)
  //   return
  // }
  if (!phone || !password) {
   ctx.fail('参数错误', -1)
   return
  }
  function allFn() {
    return new Promise(async (resolve) => {
      const res = await User.findAll({
        // attributes: ['password'],
        where: {
          phone: {
            [Op.eq]: phone
          }
        }
      })
      if (res !== undefined && res.length > 0) {
        const pwd = res[0].password
        // bcrypt密码验证
        if (decrypt(password, pwd)) {
          // 生成token
          const token = jwt.sign({
            userName: res[0].userName,
            id: res[0].id,
            phone: res[0].phone
          }, 'user_token', { expiresIn: process.env.NODE_ENV != 'development' ? '7d' : '365d' })

          await User.update({ lastLoginTime: new Date().getTime() }, {
            where: { phone: phone }
          })
          resolve({ code: 0,  data: token })
        } else {
          resolve({
            code: -1,
            msg: '登陆失败，密码错误，请重试'
          })
        }
      } else {
        resolve({
          code: -1,
          msg: '没有该用户！请注册'
        })
      }
    })
  }
  const res = await allFn()
  if (res.code === 0) {
    ctx.success(res.data, '登陆成功')
  } else {
    ctx.fail(res.msg, -1)
  }
}
// 找回密码
exports.resetPass = async(ctx) => {
  const { email, code, password } = ctx.request.body
  if (!email || !code || !password) {
    ctx.fail('参数错误', -1)
    return
  }
  function modifyUser() {
    return new Promise(async(resolve) => {
      const saveCode = await Store.hget(`nodemail:${email}`, 'code')
      const saveExpire = await Store.hget(`nodemail:${email}`, 'expire')
      // const saveEmail = await Store.hget(`nodemail:${email}`, 'email')
      console.log(saveCode, saveExpire, 'saveExpiresaveExpiresaveExpire')
      if (saveCode && saveExpire) {
        if (code.toUpperCase() ==  saveCode) {
          if (new Date().getTime() - saveExpire > 0) {
            resolve('验证码已过期，请重新尝试')
          } else {
            const update_res = await User.update({ password }, { // 数据库已经监听密码更改进行加密
              where: {
                email: email
              }
            })
            if (update_res[0] == 1) {
              resolve(0)
            } else {
              resolve('修改密码失败！服务器出错！')
            }
          }
        } else {
          resolve('请填写正确的验证码')
        }
      } else {
        resolve('验证码错误')
      }
    })
  }
  function allFn() {
    return new Promise(async(resolve) => {
      const findEmail = await User.findOne({ where: { email: email } }) // findOne 方法获得它找到的第一个条目(它可以满足提供的可选查询参数).
      if (findEmail) {
        modifyUser().then((data) => {
          resolve(data)
        })
      } else {
        resolve('该账号未注册！')
      }
    })
  }
  const res = await allFn()
  if (res === 0) {
    ctx.success('', '修改成功')
    // 注册成功清除相关信息
    Store.hmset(`nodemail:${email}`, 'code', '')
    Store.hmset(`nodemail:${email}`, 'expire', '')
    Store.hmset(`nodemail:${email}`, 'email', '')
  } else {
    ctx.fail(res, -1)
  }
}
// 注册用户
exports.register = async(ctx) => {
  const { phone, password, email, code } = ctx.request.body
  if (!phone || !password || !email || !code) {
    ctx.fail('参数错误', -1)
    return
  }
  function registerFn() {
    return new Promise(async(resolve) => {
      const saveCode = await Store.hget(`nodemail:${email}`, 'code')
      const saveExpire = await Store.hget(`nodemail:${email}`, 'expire')
      if (saveCode && saveExpire) { // 验证码和时间都有存储到的时候
        if (code.toUpperCase() ==  saveCode) { // 验证码相同的时候
          if (new Date().getTime() - saveExpire > 0) {// 验证码是否过期
            resolve('验证码已过期，请重新尝试')
          } else { // 最终创建账号
            const add_res = await User.create({ 
              phone: phone,
              password: password,
              email: email
            })
            if (add_res) {
              resolve(0)
            } else {
              resolve('注册失败！服务器出错！')
            }
          }
        } else {
          resolve('请填写正确的验证码')
        }
      } else {
        resolve('验证码错误，请重新获取')
      }
    })
  }
  function allFn() {
    return new Promise(async(resolve) => {
      const findEmail = await User.findAll({ 
        where: { [Op.or]: [{ phone: phone }, { email: email }],   }
      }) // (a = 5) OR (b = 6)
      if (findEmail.length > 0) {
        resolve('该手机号/邮箱已被注册！')
      } else {
        registerFn().then((data) => {
          resolve(data)
        })
      }
    })
  }
  const res = await allFn()
  if (res == 0) {
    ctx.success('', '注册成功')
    // 成功清楚redis缓存
    Store.hmset(`nodemail:${email}`, 'code', '')
    Store.hmset(`nodemail:${email}`, 'expire', '')
    Store.hmset(`nodemail:${email}`, 'email', '')
  } else {
    ctx.fail(res, -1)
  }
}
// 获得用户信息
exports.getInfo = async(ctx) => {
  const { getFile } = require('../models/getfile')
  const { verify } = require('../models/tokenFn')
  const userId = verify(ctx.header)
  // 根据5为满数转换百分比
  function toPercent(point) {
    let sum = point / 5
    let str  = Number(sum * 100).toFixed(2)
    str += '%'
    return str
  }

  function allFn() {
    return new Promise(async(resolve) => {
      const select_res = await User.findOne({
        where: {
          id: userId
        }
      })
      if (select_res) {
        // 获取店铺商品的评论 评分列表 并算出平均分数
        const rate_res = new Promise(async(resolve) => {
          const rate_list = await MyGoodsListRate.findAll({
            where: { adminId: userId }
          })
          if (rate_list !== undefined && rate_list.length > 0) {
            let sum = 0
            for (let i = 0; i < rate_list.length; i++) {
              sum += rate_list[i].count
            }
            let svg = toPercent(sum/rate_list.length)
            select_res['rate_count'] = svg
            resolve(rate_list)
          } else {
            select_res['rate_count'] = 0
            resolve(rate_list)
          }
        })
        const avatar_res = new Promise(async(resolve) => {
          getFile(select_res.avatar).then(url => {
            select_res.avatar = url
            resolve(select_res)
          })
        })
        const promise_all = await Promise.all([rate_res, avatar_res])
        if (promise_all) {
          resolve(select_res)
        } else {
          resolve(select_res)
        }
      } else {
        resolve(-1)
      }
    })
  }
  const res = await allFn()
  if (res !== -1) {
    ctx.success(res)
  } else {
    ctx.fail('失败')
  }
}
// 修改用户信息
// 传什么字段修改什么
exports.modify = async(ctx) => {
  const { verify } = require('../models/tokenFn')
  const data = ctx.request.body
  const userId = verify(ctx.header)

  if (!data) {
    ctx.fail('参数错误')
    return
  }
  if (data.password || data.phone || data.email) {
    ctx.fail('包含敏感信息，修改失败')
    return
  }
  function allFn() {
    return new Promise(async(resolve) => {
      for (let fag in data) {
        if (data[fag] == null || data[fag] == undefined || data[fag] == '') {
          delete data[fag]
        }
      }
      const res = await User.update(data, {
        where: {
          id: userId
        }
      })
      if (res[0] == 1) {
        resolve('修改成功')
      } else {
        resolve(-1)
      }
    })
  }
  const res = await allFn()
  if (res !== -1) {
    ctx.success('', res)
  } else {
    ctx.fail('修改失败')
  }
}
exports.modifyAccount = async(ctx) => {
  const { type, phone, email, newEmail, password, code } = ctx.request.body
  if (!type) {
    ctx.fail('参数错误')
    return
  }
  let res
  switch (type) {
    case 'phone': // 修改手机号
      res = await modifyPhone()
      break
    case 'email': // 修改绑定邮箱
      res = await modifyEmail()
      break
    case 'password': // 修改重置密码
      res = await modifyPass()
      break
  }

  if (res === 0) {
    ctx.success('', '修改成功')
    // 成功清楚redis缓存
    Store.hmset(`nodemail:${email}`, 'code', '')
    Store.hmset(`nodemail:${email}`, 'expire', '')
    Store.hmset(`nodemail:${email}`, 'email', '')
  } else {
    ctx.fail(res, -1)
  }
  // 重置密码
  function modifyPass() {
    return new Promise(async(resolve) => {
      if (!email || !password || !code) {
        resolve('参数错误')
      }
      const saveCode = await Store.hget(`nodemail:${email}`, 'code')
      const saveExpire = await Store.hget(`nodemail:${email}`, 'expire')
      if (saveCode && saveExpire) { // 验证码和时间都有存储到的时候
        if (code.toUpperCase() ==  saveCode) { // 验证码相同的时候
          if (new Date().getTime() - saveExpire > 0) { // 验证码是否过期
            resolve('验证码已过期，请重新尝试')
          } else { // 验证成功
            const res = await User.update({ password }, { where: { email }}) // 数据库已经监听密码更改进行加密
            if (res[0] == 1) {
              resolve(0)
            } else {
              resolve('重置失败')
            }
          }
        } else {
          resolve('请填写正确的验证码')
        }
      } else {
        resolve('验证码错误，请重新获取')
      }
    })
  }
  // 修改绑定邮箱
  function modifyEmail() {
    return new Promise(async(resolve) => {
      if (!email || !newEmail || !code) {
        resolve('参数错误')
      }
      const saveCode = await Store.hget(`nodemail:${email}`, 'code')
      const saveExpire = await Store.hget(`nodemail:${email}`, 'expire')
      if (saveCode && saveExpire) { // 验证码和时间都有存储到的时候
        if (code.toUpperCase() ==  saveCode) { // 验证码相同的时候
          if (new Date().getTime() - saveExpire > 0) { // 验证码是否过期
            resolve('验证码已过期，请重新尝试')
          } else { // 验证成功
            const res = await User.findOne({ where: { email: newEmail }})
            if (res) {
              resolve('该邮箱已被注册！请更换重试')
            } else { // 修改邮箱
              User.update({ email: newEmail }, { where: { email }}).then(res => {
                if (res[0] == 1) {
                  resolve(0)
                } else {
                  resolve('修改失败')
                }
              })
            }
          }
        } else {
          resolve('请填写正确的验证码')
        }
      } else {
        resolve('验证码错误，请重新获取')
      }
    })
  }
  // 修改手机号/登录账号
  function modifyPhone() {
    return new Promise(async(resolve) => {
      if (!email || !phone || !code) {
        resolve('参数错误')
      }
      const saveCode = await Store.hget(`nodemail:${email}`, 'code')
      const saveExpire = await Store.hget(`nodemail:${email}`, 'expire')
      console.log(code.toUpperCase() ==  saveCode, new Date().getTime() - saveExpire, '1111111111111111')
      if (saveCode && saveExpire) { // 验证码和时间都有存储到的时候
        if (code.toUpperCase() ==  saveCode) { // 验证码相同的时候
          if (new Date().getTime() - saveExpire > 0) { // 验证码是否过期
            resolve('验证码已过期，请重新尝试')
          } else { // 验证成功
            const res = await User.findOne({ where: { phone }})
            if (res) {
              resolve('该手机号已被注册！请更换重试')
            } else { // 修改手机号
              User.update({ phone }, { where: { email }}).then(res => {
                if (res[0] == 1) {
                  resolve(0)
                } else {
                  resolve('修改失败')
                }
              })
            }
          }
        } else {
          resolve('请填写正确的验证码')
        }
      } else {
        resolve('验证码错误，请重新获取')
      }
    })
  }
}

// 刷新token
exports.refreshToken = async(ctx) => {
  console.log(ctx.header)
  if (!ctx.header.token) {
    ctx.fail('token不存在', -1)
    return
  }
  const jwt = require('jsonwebtoken')

  function allFn() {
    return new Promise(async(resolve) => {
      jwt.verify(ctx.header.token, 'user_token', (err, authData) => {
        if (!err) {
          const token = jwt.sign({
            userName: authData.userName,
            id: authData.id,
            phone: authData.phone
          }, 'user_token', { expiresIn: process.env.NODE_ENV != 'development' ? '7d' : '365d' }) // 线下环境365天
          resolve(token)
        } else {
          resolve(-1)
        }
      })
    })
  }
  const res = await allFn()
  if (res !== -1) {
    ctx.success(res, '刷新成功')
  } else {
    ctx.fail('刷新失败')
  }
}